/* Copyright (c) 2015,2016 Lucky Byte, Inc.
 */
package com.lucky_byte.pay.jar.lualib;

import java.io.UnsupportedEncodingException;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.OneArgFunction;
import org.luaj.vm2.lib.TwoArgFunction;
import com.lucky_byte.pay.jar.ByteUtils;

/**
 * 处理 GB18030 字符串
 */
public class LuaGB18030 extends TwoArgFunction
{
	private static final Logger logger = LogManager.getLogger();

	@Override
	public LuaValue call(LuaValue modname, LuaValue env) {
		LuaValue library = tableOf();
		env.set("gb18030", library);

		library.set("len", new GBLength());
		library.set("str", new GBString());
		return library;
	}

	/**
	 * 求字符串转换为 GB18030 后的字节数
	 */
	class GBLength extends OneArgFunction
	{
		@Override
		public LuaValue call(LuaValue arg) {
			String str = arg.checkjstring();
			try {
				return LuaValue.valueOf(str.getBytes("GB18030").length);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
				return LuaValue.valueOf(0);
			}
		}
	}

	/**
	 * 将 Lua 中 GB18030 编码的字节转换为 Java 字符串
	 */
	class GBString extends OneArgFunction
	{
		@Override
		public LuaValue call(LuaValue arg) {
			if (arg.isnil()) {
				logger.error("gb18030()的第一个参数必须是 Lua 字符串.");
				return LuaValue.NIL;
			}
			if (!(arg instanceof LuaString)) {
				logger.error("gb18030()的第一个参数必须是 Lua 字符串.");
				return LuaValue.NIL;
			}
			try {
				LuaString string = (LuaString) arg;
				byte[] bytes = this.removeHalfHanzi(string.m_bytes);
				return LuaValue.valueOf(new String(bytes, "GB18030"));
			} catch (UnsupportedEncodingException e) {
				logger.catching(e);
				return LuaValue.NIL;
			}
		}

		/**
		 * 删除半个汉字
		 */
		private byte[] removeHalfHanzi(byte[] bytes) {
			byte[] ret_bytes = new byte[bytes.length];
			boolean half = false;
			int j = 0;
			for (int i = 0; i < bytes.length; i++) {
				if ((bytes[i] & 0x80) != 0) {
					if (half) {
						ret_bytes[j] = bytes[i - 1];
						ret_bytes[j + 1] = bytes[i];
						j += 2;
						half = false;
					} else {
						half = true;
					}
				} else {
					ret_bytes[j] = bytes[i];
					j++;
					half = false;
				}
			}
			return ByteUtils.truncate(ret_bytes, 0, j);
		}
	}

}